package com.yuantu.judiciary.serviceimpl;

import com.yuantu.judiciary.common.SysCode;
import com.yuantu.judiciary.dao.IAccountDao;
import com.yuantu.judiciary.dao.IInviteCodeDao;
import com.yuantu.judiciary.dao.IInviteRecordDao;
import com.yuantu.judiciary.dao.IQueryRecordDao;
import com.yuantu.judiciary.exception.ServiceException;
import com.yuantu.judiciary.exception.enums.AccountExceptionEnum;
import com.yuantu.judiciary.model.domain.AccountDO;
import com.yuantu.judiciary.model.domain.InviteCodeDO;
import com.yuantu.judiciary.model.domain.InviteRecordDO;
import com.yuantu.judiciary.model.enums.AuthResultType;
import com.yuantu.judiciary.model.enums.InviteCodeType;
import com.yuantu.judiciary.model.vo.DistributorStatisticsExcelVO;
import com.yuantu.judiciary.model.vo.DistributorStatisticsVO;
import com.yuantu.judiciary.service.IDistributorService;
import com.yuantu.judiciary.utils.AssertUtil;
import com.yuantu.judiciary.utils.ExcelUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务商管理模块
 *
 * @author syw
 * @since 2023-12-15
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class DistributorServiceImpl implements IDistributorService {

    private final IAccountDao accountDao;
    private final IInviteCodeDao inviteCodeDao;
    private final IInviteRecordDao inviteRecordDao;
    private final IQueryRecordDao queryRecordDao;

    @Override
    public List<DistributorStatisticsVO> getStatistics(Long accountId) {
        AccountDO account = accountDao.findByIdAndDeletedFalse(accountId);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(account), AccountExceptionEnum.ACCOUNT_NOT_EXIST);
        List<InviteCodeDO> distributorCodes = inviteCodeDao.getInviteCodeByOperatorIdAndTypeAndDeletedFalseOrderByIdDesc(accountId, InviteCodeType.DISTRIBUTE);
        if (CollectionUtils.isEmpty(distributorCodes)) {
            return Collections.emptyList();
        }
        // 获取邀请注册记录
        InviteCodeDO distributorCode = distributorCodes.get(0);
        List<InviteRecordDO> recordList = inviteRecordDao.findRecordByInviteCodeAndDeletedFalse(distributorCode.getInviteCode());
        if (CollectionUtils.isEmpty(recordList)) {
            return Collections.emptyList();
        }
        // 获取邀请注册用户信息
        List<Long> accountIds = recordList.stream().map(InviteRecordDO::getCreatorId).collect(Collectors.toList());
        List<IAccountDao.AccountUserInfo> accountInfo = accountDao.getAccountInfo(accountIds);
        if (CollectionUtils.isEmpty(accountInfo)) {
            return Collections.emptyList();
        }
        Map<Long, IAccountDao.AccountUserInfo> accountMap = accountInfo.stream().collect(Collectors.toMap(IAccountDao.AccountUserInfo::getAccountId, v -> v));
        // 获取注册用户分配查询次数
        List<InviteCodeDO> inviteCodes = inviteCodeDao.getInviteCodeByOperatorIdAndTypeAndDeletedFalseOrderByIdDesc(accountId, InviteCodeType.TRIAL);
        Map<String, InviteCodeDO> codeMap = CollectionUtils.isEmpty(inviteCodes) ? new HashMap<>()
                : inviteCodes.stream().collect(Collectors.toMap(InviteCodeDO::getInviteCode, v -> v));
        Map<Long, String> recordMap = CollectionUtils.isEmpty(inviteCodes) ? new HashMap<>()
                : inviteRecordDao.findRecordByInviteCodeInAndDeletedFalse(new ArrayList<>(codeMap.keySet())).stream()
                        .collect(Collectors.toMap(InviteRecordDO::getCreatorId, InviteRecordDO::getInviteCode));

        return recordList.stream().map(data -> {
            DistributorStatisticsVO res = new DistributorStatisticsVO();
            if (accountMap.containsKey(data.getCreatorId())) {
                IAccountDao.AccountUserInfo accountUserInfo = accountMap.get(data.getCreatorId());
                res.setEnterName(StringUtils.isNotBlank(accountMap.get(data.getCreatorId()).getEnterName())
                        ? accountMap.get(data.getCreatorId()).getEnterName()
                        : accountMap.get(data.getCreatorId()).getUsername());

                List<AccountDO> orgAccounts = accountDao.findAccountByOrganizationIdAndDeletedFalse(accountUserInfo.getOrganizationId());
                if (!CollectionUtils.isEmpty(orgAccounts)) {
                    Integer totalUseNum = queryRecordDao.countDistinctByCreatorIdInAndAuthorizedResultAndDeletedFalse(
                            orgAccounts.stream().map(AccountDO::getId).collect(Collectors.toList()), AuthResultType.AUTHORIZED
                    );
                    res.setUseNum(totalUseNum);
                }
            }
            if (recordMap.containsKey(data.getCreatorId())) {
                String code = recordMap.get(data.getCreatorId());
                if (codeMap.containsKey(code)) {
                    res.setDistributeNum(codeMap.get(code).getVipUseTimes());
                }
            }

            return res;
        }).collect(Collectors.toList());
    }

    @Override
    public Boolean downloadStatistics(HttpServletResponse response, Long accountId) {
        AccountDO account = accountDao.findByIdAndDeletedFalse(accountId);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(account), AccountExceptionEnum.ACCOUNT_NOT_EXIST);
        List<InviteCodeDO> distributorCodes = inviteCodeDao.getInviteCodeByOperatorIdAndTypeAndDeletedFalseOrderByIdDesc(accountId, InviteCodeType.DISTRIBUTE);
        List<DistributorStatisticsExcelVO> exportList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(distributorCodes)) {
            // 获取邀请注册记录
            InviteCodeDO distributorCode = distributorCodes.get(0);
            List<InviteRecordDO> recordList = inviteRecordDao.findRecordByInviteCodeAndDeletedFalse(distributorCode.getInviteCode());
            if (!CollectionUtils.isEmpty(recordList)) {
                // 获取邀请注册用户信息
                List<Long> accountIds = recordList.stream().map(InviteRecordDO::getCreatorId).collect(Collectors.toList());
                List<IAccountDao.AccountUserInfo> accountInfo = accountDao.getAccountInfo(accountIds);
                if (!CollectionUtils.isEmpty(accountInfo)) {
                    Map<Long, IAccountDao.AccountUserInfo> accountMap = accountInfo.stream().collect(Collectors.toMap(IAccountDao.AccountUserInfo::getAccountId, v -> v));
                    // 获取注册用户分配查询次数
                    List<InviteCodeDO> inviteCodes = inviteCodeDao.getInviteCodeByOperatorIdAndTypeAndDeletedFalseOrderByIdDesc(accountId, InviteCodeType.TRIAL);
                    Map<String, InviteCodeDO> codeMap = CollectionUtils.isEmpty(inviteCodes) ? new HashMap<>()
                            : inviteCodes.stream().collect(Collectors.toMap(InviteCodeDO::getInviteCode, v -> v));
                    Map<Long, String> recordMap = CollectionUtils.isEmpty(inviteCodes) ? new HashMap<>()
                            : inviteRecordDao.findRecordByInviteCodeInAndDeletedFalse(new ArrayList<>(codeMap.keySet())).stream()
                            .collect(Collectors.toMap(InviteRecordDO::getCreatorId, InviteRecordDO::getInviteCode));

                    exportList = recordList.stream().map(data -> {
                        DistributorStatisticsExcelVO res = new DistributorStatisticsExcelVO();
                        if (accountMap.containsKey(data.getCreatorId())) {
                            IAccountDao.AccountUserInfo accountUserInfo = accountMap.get(data.getCreatorId());
                            res.setEnterName(StringUtils.isNotBlank(accountUserInfo.getEnterName())
                                    ? accountUserInfo.getEnterName()
                                    : accountUserInfo.getUsername());
                            res.setUsername(accountUserInfo.getUsername());
                            res.setPhone(accountUserInfo.getPhone());
                            if (accountUserInfo.getCreateTime() != null) {
                                res.setCreateTime(new Date(accountUserInfo.getCreateTime().getTime()));
                            }

                            List<AccountDO> orgAccounts = accountDao.findAccountByOrganizationIdAndDeletedFalse(accountUserInfo.getOrganizationId());
                            if (!CollectionUtils.isEmpty(orgAccounts)) {
                                Integer totalUseNum = queryRecordDao.countDistinctByCreatorIdInAndAuthorizedResultAndDeletedFalse(
                                        orgAccounts.stream().map(AccountDO::getId).collect(Collectors.toList()), AuthResultType.AUTHORIZED
                                );
                                res.setUseNum(totalUseNum);
                            }
                        }
                        if (recordMap.containsKey(data.getCreatorId())) {
                            String code = recordMap.get(data.getCreatorId());
                            if (codeMap.containsKey(code)) {
                                res.setDistributeNum(codeMap.get(code).getVipUseTimes());
                            }
                        }

                        return res;
                    }).collect(Collectors.toList());
                }
            }
        }

        try {
            ExcelUtil.exportExcel("数据统计", "统计信息", DistributorStatisticsExcelVO.class, exportList, "统计信息表", response);
        } catch (Exception e) {
            log.error("用户【" + accountId + "】服务商数据统计导出失败：", e);
            throw new ServiceException(SysCode.FILE_EXPORT_ERROR);
        }

        return true;
    }

}
